package com.cencat.merchant.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.merchant.entity.Dispatch;
import com.cencat.merchant.dto.DispatchQueryDTO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 调度管理Mapper接口
 * 提供调度数据的增删改查、统计分析、智能匹配等数据访问功能
 * 
 * @author cencat
 * @version 1.0
 * @since 2025-01-20
 */
@Mapper
public interface DispatchMapper extends BaseMapper<Dispatch> {

    /**
     * 分页查询调度列表
     * 
     * @param page 分页参数
     * @param queryDTO 查询条件
     * @return 调度分页数据
     */
    Page<Dispatch> selectDispatchPage(Page<Dispatch> page, @Param("query") DispatchQueryDTO queryDTO);

    /**
     * 批量更新调度状态
     * 
     * @param ids 调度ID列表
     * @param status 新状态
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE dispatch SET status = #{status}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdateStatus(@Param("ids") List<Long> ids, @Param("status") String status);

    /**
     * 批量更新调度优先级
     * 
     * @param ids 调度ID列表
     * @param priority 优先级
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE dispatch SET priority = #{priority}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdatePriority(@Param("ids") List<Long> ids, @Param("priority") Integer priority);

    /**
     * 批量分配司机
     * 
     * @param ids 调度ID列表
     * @param driverId 司机ID
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE dispatch SET driver_id = #{driverId}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchAssignDriver(@Param("ids") List<Long> ids, @Param("driverId") Long driverId);

    /**
     * 批量分配车辆
     * 
     * @param ids 调度ID列表
     * @param vehicleId 车辆ID
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE dispatch SET vehicle_id = #{vehicleId}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchAssignVehicle(@Param("ids") List<Long> ids, @Param("vehicleId") Long vehicleId);

    /**
     * 根据状态统计调度数量
     * 
     * @param status 调度状态
     * @return 调度数量
     */
    @Select("SELECT COUNT(*) FROM dispatch WHERE status = #{status}")
    Long countByStatus(@Param("status") String status);

    /**
     * 根据调度类型统计调度数量
     * 
     * @param dispatchType 调度类型
     * @return 调度数量
     */
    @Select("SELECT COUNT(*) FROM dispatch WHERE dispatch_type = #{dispatchType}")
    Long countByDispatchType(@Param("dispatchType") String dispatchType);

    /**
     * 计算平均调度时长
     * 
     * @return 平均时长（分钟）
     */
    @Select("SELECT AVG(TIMESTAMPDIFF(MINUTE, start_time, end_time)) FROM dispatch WHERE status = 'COMPLETED'")
    BigDecimal calculateAverageDuration();

    /**
     * 查询待调度列表
     * 
     * @param limit 限制数量
     * @return 待调度列表
     */
    @Select("SELECT * FROM dispatch WHERE status = 'PENDING' ORDER BY priority DESC, create_time ASC LIMIT #{limit}")
    List<Dispatch> selectPendingDispatches(@Param("limit") Integer limit);

    /**
     * 查询进行中调度列表
     * 
     * @param limit 限制数量
     * @return 进行中调度列表
     */
    @Select("SELECT * FROM dispatch WHERE status = 'IN_PROGRESS' ORDER BY update_time DESC LIMIT #{limit}")
    List<Dispatch> selectInProgressDispatches(@Param("limit") Integer limit);

    /**
     * 查询已完成调度列表
     * 
     * @param limit 限制数量
     * @return 已完成调度列表
     */
    @Select("SELECT * FROM dispatch WHERE status = 'COMPLETED' ORDER BY end_time DESC LIMIT #{limit}")
    List<Dispatch> selectCompletedDispatches(@Param("limit") Integer limit);

    /**
     * 查询紧急调度列表
     * 
     * @param limit 限制数量
     * @return 紧急调度列表
     */
    @Select("SELECT * FROM dispatch WHERE priority >= 8 AND status IN ('PENDING', 'IN_PROGRESS') ORDER BY priority DESC, create_time ASC LIMIT #{limit}")
    List<Dispatch> selectUrgentDispatches(@Param("limit") Integer limit);

    /**
     * 根据调度类型查询调度列表
     * 
     * @param dispatchType 调度类型
     * @param status 调度状态
     * @param limit 限制数量
     * @return 调度列表
     */
    @Select("<script>" +
            "SELECT * FROM dispatch WHERE dispatch_type = #{dispatchType} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Dispatch> selectDispatchesByType(@Param("dispatchType") String dispatchType, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 根据司机ID查询调度列表
     * 
     * @param driverId 司机ID
     * @param status 调度状态
     * @param limit 限制数量
     * @return 调度列表
     */
    @Select("<script>" +
            "SELECT * FROM dispatch WHERE driver_id = #{driverId} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Dispatch> selectDispatchesByDriver(@Param("driverId") Long driverId, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 根据车辆ID查询调度列表
     * 
     * @param vehicleId 车辆ID
     * @param status 调度状态
     * @param limit 限制数量
     * @return 调度列表
     */
    @Select("<script>" +
            "SELECT * FROM dispatch WHERE vehicle_id = #{vehicleId} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Dispatch> selectDispatchesByVehicle(@Param("vehicleId") Long vehicleId, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 根据路线ID查询调度列表
     * 
     * @param routeId 路线ID
     * @param status 调度状态
     * @param limit 限制数量
     * @return 调度列表
     */
    @Select("<script>" +
            "SELECT * FROM dispatch WHERE route_id = #{routeId} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Dispatch> selectDispatchesByRoute(@Param("routeId") Long routeId, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 根据时间范围查询调度列表
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param status 调度状态
     * @param limit 限制数量
     * @return 调度列表
     */
    @Select("<script>" +
            "SELECT * FROM dispatch WHERE start_time BETWEEN #{startTime} AND #{endTime} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY start_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Dispatch> selectDispatchesByTimeRange(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 智能匹配调度
     * 
     * @param dispatchType 调度类型
     * @param routeId 路线ID
     * @param priority 最小优先级
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param limit 限制数量
     * @return 匹配的调度列表
     */
    @Select("<script>" +
            "SELECT * FROM dispatch " +
            "WHERE status = 'PENDING' " +
            "<if test='dispatchType != null and dispatchType != \"\">" +
            "AND dispatch_type = #{dispatchType} " +
            "</if>" +
            "<if test='routeId != null'>" +
            "AND route_id = #{routeId} " +
            "</if>" +
            "<if test='priority != null'>" +
            "AND priority >= #{priority} " +
            "</if>" +
            "<if test='startTime != null'>" +
            "AND start_time >= #{startTime} " +
            "</if>" +
            "<if test='endTime != null'>" +
            "AND end_time <= #{endTime} " +
            "</if>" +
            "ORDER BY priority DESC, create_time ASC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Dispatch> selectMatchedDispatches(@Param("dispatchType") String dispatchType, @Param("routeId") Long routeId, @Param("priority") Integer priority, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("limit") Integer limit);

    /**
     * 检查调度编码是否存在
     * 
     * @param dispatchCode 调度编码
     * @param excludeId 排除的调度ID
     * @return 存在数量
     */
    @Select("<script>" +
            "SELECT COUNT(*) FROM dispatch WHERE dispatch_code = #{dispatchCode} " +
            "<if test='excludeId != null'>" +
            "AND id != #{excludeId}" +
            "</if>" +
            "</script>")
    int existsByDispatchCode(@Param("dispatchCode") String dispatchCode, @Param("excludeId") Long excludeId);

    /**
     * 搜索调度
     * 
     * @param keyword 关键词
     * @param searchType 搜索类型
     * @param limit 限制数量
     * @return 调度列表
     */
    @Select("<script>" +
            "SELECT * FROM dispatch WHERE 1=1 " +
            "<choose>" +
            "<when test='searchType == \"code\"'>" +
            "AND dispatch_code LIKE CONCAT('%', #{keyword}, '%') " +
            "</when>" +
            "<when test='searchType == \"description\"'>" +
            "AND description LIKE CONCAT('%', #{keyword}, '%') " +
            "</when>" +
            "<otherwise>" +
            "AND (dispatch_code LIKE CONCAT('%', #{keyword}, '%') " +
            "OR description LIKE CONCAT('%', #{keyword}, '%')) " +
            "</otherwise>" +
            "</choose>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Dispatch> searchDispatches(@Param("keyword") String keyword, @Param("searchType") String searchType, @Param("limit") Integer limit);

    /**
     * 查询调度列表（用于导出）
     * 
     * @param queryDTO 查询条件
     * @return 调度列表
     */
    List<Dispatch> selectDispatchList(@Param("query") DispatchQueryDTO queryDTO);

    /**
     * 计算指定时间范围内的调度数量
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param status 调度状态
     * @return 调度数量
     */
    @Select("<script>" +
            "SELECT COUNT(*) FROM dispatch " +
            "WHERE create_time BETWEEN #{startTime} AND #{endTime} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status}" +
            "</if>" +
            "</script>")
    Integer calculateDispatchCount(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("status") String status);

    /**
     * 计算指定时间范围内的平均调度时长
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 平均时长（分钟）
     */
    @Select("SELECT AVG(TIMESTAMPDIFF(MINUTE, start_time, end_time)) FROM dispatch " +
            "WHERE create_time BETWEEN #{startTime} AND #{endTime} AND status = 'COMPLETED'")
    Double calculateAverageDurationByTime(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取调度趋势数据
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param trendType 趋势类型
     * @return 趋势数据
     */
    List<Map<String, Object>> selectDispatchTrends(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("trendType") String trendType);

    /**
     * 获取调度排行榜
     * 
     * @param rankType 排行类型
     * @param limit 限制数量
     * @return 排行榜数据
     */
    List<Map<String, Object>> selectDispatchRanking(@Param("rankType") String rankType, @Param("limit") Integer limit);

    /**
     * 获取调度分布数据
     * 
     * @param distributionType 分布类型
     * @return 分布数据
     */
    List<Map<String, Object>> selectDispatchDistribution(@Param("distributionType") String distributionType);

    /**
     * 更新调度开始时间
     * 
     * @param dispatchId 调度ID
     * @param startTime 开始时间
     * @return 更新记录数
     */
    @Update("UPDATE dispatch SET start_time = #{startTime}, status = 'IN_PROGRESS', update_time = NOW() WHERE id = #{dispatchId}")
    int updateStartTime(@Param("dispatchId") Long dispatchId, @Param("startTime") LocalDateTime startTime);

    /**
     * 更新调度结束时间
     * 
     * @param dispatchId 调度ID
     * @param endTime 结束时间
     * @return 更新记录数
     */
    @Update("UPDATE dispatch SET end_time = #{endTime}, status = 'COMPLETED', update_time = NOW() WHERE id = #{dispatchId}")
    int updateEndTime(@Param("dispatchId") Long dispatchId, @Param("endTime") LocalDateTime endTime);

    /**
     * 更新调度进度
     * 
     * @param dispatchId 调度ID
     * @param progress 进度百分比
     * @return 更新记录数
     */
    @Update("UPDATE dispatch SET progress = #{progress}, update_time = NOW() WHERE id = #{dispatchId}")
    int updateProgress(@Param("dispatchId") Long dispatchId, @Param("progress") Integer progress);

    /**
     * 批量更新调度进度
     * 
     * @param dispatchIds 调度ID列表
     * @param progress 进度百分比
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE dispatch SET progress = #{progress}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='dispatchIds' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdateProgress(@Param("dispatchIds") List<Long> dispatchIds, @Param("progress") Integer progress);

    /**
     * 获取调度统计数据
     * 
     * @param dispatchId 调度ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 统计数据
     */
    Map<String, Object> selectDispatchStats(@Param("dispatchId") Long dispatchId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取调度效率统计
     * 
     * @param dispatchId 调度ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 效率统计数据
     */
    Map<String, Object> selectDispatchEfficiencyStats(@Param("dispatchId") Long dispatchId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取调度成本统计
     * 
     * @param dispatchId 调度ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 成本统计数据
     */
    Map<String, Object> selectDispatchCostStats(@Param("dispatchId") Long dispatchId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取司机调度统计
     * 
     * @param driverId 司机ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 司机调度统计数据
     */
    Map<String, Object> selectDriverDispatchStats(@Param("driverId") Long driverId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取车辆调度统计
     * 
     * @param vehicleId 车辆ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 车辆调度统计数据
     */
    Map<String, Object> selectVehicleDispatchStats(@Param("vehicleId") Long vehicleId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取路线调度统计
     * 
     * @param routeId 路线ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 路线调度统计数据
     */
    Map<String, Object> selectRouteDispatchStats(@Param("routeId") Long routeId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
}